package de.tum.in.eist.poll.client;

import java.util.List;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.visualization.client.AbstractDataTable.ColumnType;
import com.google.gwt.visualization.client.DataTable;
import com.google.gwt.visualization.client.VisualizationUtils;
import com.google.gwt.visualization.client.visualizations.PieChart;

import de.tum.in.eist.poll.shared.Feedback;
import de.tum.in.eist.poll.shared.Lecturer;
import de.tum.in.eist.poll.shared.User;

public class FeedbackScreen implements ViewInterface {
	private boolean is_visible = false;
	
	// Attributes that control which information should be shown on the feedback screen.
	// Whenever the feedback screen gets updated, these attributes get updated too.
	private boolean allow_submit = false;
	private boolean show_statistics = false;
	private boolean show_comments = true;
	
	// The available choices for the rating.
	private final String[] rating = { "Very unsatisfied", "Unsatisfied", "Neutral", "Satisfied", "Very Satisfied" };
	
	// Widgets on this page.
	private Anchor back_link;
	private RadioButton rating_button1 = new RadioButton("RatingButtons", rating[0]);
	private RadioButton rating_button2 = new RadioButton("RatingButtons", rating[1]);
	private RadioButton rating_button3 = new RadioButton("RatingButtons", rating[2]);
	private RadioButton rating_button4 = new RadioButton("RatingButtons", rating[3]);
	private RadioButton rating_button5 = new RadioButton("RatingButtons", rating[4]);
	private Label positive_feedback_label = new Label("What did you like most?");
	private Label negative_feedback_label = new Label("What did you dislike or did not understand at all?");
	private TextArea positive_feedback = new TextArea();
	private TextArea negative_feedback = new TextArea();
	private Button submit_feedback = new Button("Submit");
	private Grid feedback_grid = new Grid();
	private PieChart pie_chart = null;
	private boolean visualisation_api_loaded = false;
	private Timer refresh_timer = null;
	// Intervall between refresh attempts.
	private int refresh_interval = 5000;
	
	public FeedbackScreen(final EIST_POLL controller) {
		// Create the widgets and event handlers.
		back_link = new Anchor("Back");
		back_link.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(final ClickEvent event) {
				controller.showLectureScreen(null);
			}
		});
		rating_button1.setValue(true);
		submit_feedback.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				controller.submitFeedback(getRating(), positive_feedback.getText(),  negative_feedback.getText());
			}
		});
		
		// Add id or class attributes to the elements, so we can style them.
		feedback_grid.getElement().setId("feedbackGrid");
		back_link.getElement().setId("backLink");
		submit_feedback.getElement().setId("feedbackSubmit");
		positive_feedback.getElement().setClassName("feedbackText");
		negative_feedback.getElement().setClassName("feedbackText");		

	    // Load the visualization api, passing the onLoadCallback to be called
	    // when loading is done.
	    VisualizationUtils.loadVisualizationApi(new Runnable() {
	    	public void run() {
	    		visualisation_api_loaded = true;
	    	}
	    }, PieChart.PACKAGE);
	    
	    // Create a timer that periodically tries to refresh the feedback screen.
	    refresh_timer = new Timer() {
			@Override
			public void run() {
				controller.refreshFeedbackScreen();
				refresh_timer.schedule(refresh_interval);
			}
		};
	}
	
	/**
	 * Returns a value representing the currently selected rating.
	 */
	private int getRating() {
		if(rating_button1.getValue())
			return 1;
		else if(rating_button2.getValue())
			return 2;
		else if(rating_button3.getValue())
			return 3;
		else if(rating_button4.getValue())
			return 4;
		else if(rating_button5.getValue())
			return 5;
		
		return 0;
	}
	
	@Override
	public void show() {
		if(is_visible) return;
		is_visible = true;
		
		// Change the subtitle of the page.
		DOM.setInnerHTML(DOM.getElementById("subtitle"), "Feedback");
		
		// Clear the textboxes.
		positive_feedback.setText("");
		negative_feedback.setText("");
		
		// Submit form.
		RootPanel r = RootPanel.get("content");
		r.add(back_link);
		
		if(allow_submit) {
			r.add(rating_button1);
			r.add(rating_button2);
			r.add(rating_button3);
			r.add(rating_button4);
			r.add(rating_button5);
			
			r.add(positive_feedback_label);
			r.add(positive_feedback);
			r.add(negative_feedback_label);
			r.add(negative_feedback);
			r.add(submit_feedback);
		}
		
		if(show_statistics) {
			r.add(pie_chart);
			refresh_timer.schedule(refresh_interval);
		}
		
		if(show_comments) {
			r.add(feedback_grid);
		}
	}

	@Override
	public void hide() {
		if(!is_visible) return;
		is_visible = false;
		
		RootPanel r = RootPanel.get("content");
		r.remove(back_link);
		
		r.remove(rating_button1);
		r.remove(rating_button2);
		r.remove(rating_button3);
		r.remove(rating_button4);
		r.remove(rating_button5);
		
		r.remove(positive_feedback_label);
		r.remove(positive_feedback);
		r.remove(negative_feedback_label);
		r.remove(negative_feedback);
		
		r.remove(submit_feedback);
		r.remove(pie_chart);

		r.remove(feedback_grid);
		
		// We don't want the refresh timer to fire after the feedback page was hidden.
		refresh_timer.cancel();
	}
	
	public boolean isVisible() {
		return is_visible;
	}
	
	/**
	 * Piechart options.
	 */
	private PieChart.Options createPieChartOptions() {
		PieChart.Options options = PieChart.Options.create();
		options.setWidth(400);
		options.setHeight(240);
		options.set3D(true);
		options.setTitle("View");
		
		// This should be moved to the css file.
		options.setBackgroundColor("#DDDDDD");
		options.setLegendBackgroundColor("#DDDDDD");
		
		return options;
	}
	
	/**
	 * Called to bring the widgets on this page up to date with current feedback.
	 * @param feedback
	 * @param current_user
	 */
	public void updateFeedback(List<Feedback> feedback, User current_user) {
		feedback_grid = new Grid(feedback.size() + 1, 2);
		DOM.setElementAttribute(feedback_grid.getElement(), "id", "feedbackGrid");
		feedback_grid.setHTML(0, 0, "<span class=\"tableHeader\">Positive comments</span>");
		feedback_grid.setHTML(0, 1, "<span class=\"tableHeader\">Negative comments</span>");
		feedback_grid.setCellPadding(0);
		feedback_grid.setCellSpacing(0);
		
		int[] bewertungen = {0, 0, 0, 0, 0};
		
		// Different types of users see different information on this page.
		if(current_user instanceof Lecturer) {
			allow_submit = false;
			show_statistics = true;
			show_comments = true;
		} else {
			allow_submit = true;
			show_statistics = false;
			show_comments = false;
		}
		
		for(int i = 0; i < feedback.size(); ++i) {
			Feedback f = feedback.get(i);
			
			// We don't allow submits if the current user already submitted.
			// Also, we don't show statistics to users that did not yet vote.
			if(f.getStudent().equals(current_user)) {
				allow_submit = false;
				show_statistics = true;
			}
			
			// Add the comments to the feedback grid.
			++bewertungen[f.getBewertung() - 1];
			feedback_grid.setText(i+1, 0, f.getPosComm());
			feedback_grid.setText(i+1, 1, f.getNegComm());
		}
		
		// Create the pie chart.
		if(visualisation_api_loaded) {
			DataTable data = DataTable.create();
		    data.addColumn(ColumnType.STRING, "Rating");
			data.addColumn(ColumnType.NUMBER, "Number of votes");
			data.addRows(5);
			for(int i = 0; i < 5; ++i) {
			    data.setValue(i, 0, rating[i]);
			    data.setValue(i, 1, bewertungen[i]);
			}
			pie_chart = new PieChart(data, createPieChartOptions());
		} else {
			Window.alert("Failed to load visualisation API, graphical data representation is not available!\n\n" + 
						 "Please make sure you are online, so that the visualisation API can be loaded from www.goole.com!");
		}
	}
}
